
import java.util.ArrayList;
import java.util.HashMap;

public class TablaSimbolos
{
	/**
	 * Lista de simbolos que contiene la tabla.
	 */
	private HashMap<String, Simbolo> simbolos;
	/**
	 * Tabla padre ( contiene a la tabla actual ).
	 */
	private TablaSimbolos padre;
	/**
	 * Traducción de la tabla actual, incluye las traducciones de todas las tablas hijo.
	 */
	private String traduccion;
	
	/**
	 * Constructor de clase.
	 */
	public TablaSimbolos()
	{
		simbolos = new HashMap<String, Simbolo>();
		padre = null;
	}

	/**
	 * Constructor.
	 * @param padre Tabla padre. 
	 */
	public TablaSimbolos(TablaSimbolos padre)
	{
		this.padre = padre;
		simbolos = new HashMap<String, Simbolo>();
	}
	
	/**
	 * Obtiene la tabla padre de una tabla.
	 * @return Tabla padre.
	 */
	public TablaSimbolos getPadre()
	{
		return padre;
	}

	/**
	 * Obtiene la traducción de la tabla.
	 * @return Traducción de la tabla.
	 */
	public String getTraduccion()
	{
		return traduccion;
	}
	
	/**
	 * Obtiene un simbolo de la tabla.
	 * @return Lista de simbolos de la tabla.
	 */
	public Simbolo getSimbolo( String name )
	{
		Simbolo t = simbolos.get(name);
		
		if ( t != null )
		{
			return t;
		}
		else
		{
			if ( padre != null )
			{
				return padre.getSimbolo( name );
			}
			else
			{
				return null;
			}
		}
	}
	
	/**
	 * Cambia la tabla padre.
	 * @param padre Nueva tabla padre.
	 */
	public void setPadre(TablaSimbolos padre)
	{
		this.padre = padre;
	}

	/**
	 * Cambia los simbolos de uan tabla.
	 * @param simbolos Nuevos simbolos.
	 */
	public void setSimbolos( HashMap<String, Simbolo> simbolos)
	{
		this.simbolos = simbolos;
	}

	/**
	 * Cambia la traducción
	 * @param traduccion Nueva traducción.
	 */
	public void setTraduccion(String traduccion)
	{
		this.traduccion = traduccion;
	}
	
	/**
	 * Comprueba si existe un simbolo en todos los ambitos.
	 * @param s Simbolo a buscar.
	 * @return Cierto si se encuentra el simbolo y falso en caso contrario.
	 */
	public boolean existe( Simbolo s )
	{
		Simbolo t = simbolos.get(s.getNombre());
		
		if ( t != null )
		{
			return true;
		}
		else
		{
			if ( padre != null )
			{
				return padre.existe(s);
			}
			else
			{
				return false;
			}
		}
	}
	
	/**
	 * Comprueba si existe en simbolo en el ámbito actual.
	 * @param s Simbolo a comprobar.
	 * @return Cierto si existe el simbolo en el ambito y falso en caso contrario.
	 */
	public boolean existeEnAmbito( Simbolo s )
	{
		Simbolo t = simbolos.get(s.getNombre());
		
		if ( t == null )
		{
			return false;
		}
		else
		{
			return ( t.equals(s) );
		}
	}
	
	/**
	 * Comprueba si un simbolo es una función.
	 * @param s Simbolo a comprobar.
	 * @return Cierto si es una función falso en caso contrario.
	 */
	public boolean isFuncion( Simbolo s )
	{
		Simbolo t = simbolos.get(s.getNombre());
		
		if ( t != null )
		{
			return ( t.getTipo() == Simbolo.FUNCION );
		}
		else
		{
			if ( padre != null )
			{
				return padre.isFuncion(s);
			}
			else
			{
				return false;
			}
		}
	}
	
	/**
	 * Añade un nuevo simbolo a la tabla.
	 * @param s Simbolo a instertar.
	 * @return Devuelve true si se ha podido insertar el simbolo y false si ya existia.
	 */
	public boolean addSimbolo ( Simbolo s )
	{
		if ( this.existeEnAmbito(s) )
		{
			return false;
		}
		else
		{
			simbolos.put(s.getNombre(), s);
			return true;
		}
	}
	
	public TablaSimbolos pop()
	{
		if ( padre != null )
		{
			padre.traduccion = this.toString();
		}
		return ( this.padre );
	}
	
	public TablaSimbolos push()
	{
		TablaSimbolos tablaNueva = new TablaSimbolos();
		tablaNueva.padre = this;
		return tablaNueva;
	}
	
	@Override
	public String toString()
	{
		StringBuilder trad = new StringBuilder();
		
		return trad.toString();
	}
}
